package org.codehaus.activemq.message;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.util.Properties;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.TemporaryQueue;
import javax.jms.TemporaryTopic;
import javax.jms.Topic;
import org.codehaus.activemq.jndi.JNDIBaseStorable;

public abstract class ActiveMQDestination extends JNDIBaseStorable
  implements Destination, Comparable, Serializable
{
  private static final int NULL_DESTINATION = 10;
  private static final String TEMP_PREFIX = "{TD{";
  private static final String TEMP_POSTFIX = "}TD}";
  public static final int ACTIVEMQ_TOPIC = 1;
  public static final int ACTIVEMQ_TEMPORARY_TOPIC = 2;
  public static final int ACTIVEMQ_QUEUE = 3;
  public static final int ACTIVEMQ_TEMPORARY_QUEUE = 4;
  private String physicalName;

  public static String inspect(Destination destination)
  {
    if ((destination instanceof Topic)) {
      return "Topic(" + destination.toString() + ")";
    }

    return "Queue(" + destination.toString() + ")";
  }

  protected ActiveMQDestination()
  {
  }

  protected ActiveMQDestination(String name)
  {
    this.physicalName = name;
  }

  public int compareTo(Object o)
  {
    if ((o instanceof ActiveMQDestination)) {
      return compareTo((ActiveMQDestination)o);
    }
    return -1;
  }

  public int compareTo(ActiveMQDestination that)
  {
    int answer = 0;
    if (this.physicalName != that.physicalName) {
      if (this.physicalName == null) {
        return -1;
      }
      if (that.physicalName == null) {
        return 1;
      }
      answer = this.physicalName.compareTo(that.physicalName);
    }
    if (answer == 0) {
      if (isTopic()) {
        if (that.isQueue()) {
          return 1;
        }

      }
      else if (that.isTopic()) {
        return -1;
      }
    }

    return answer;
  }

  public abstract int getDestinationType();

  public String getPhysicalName()
  {
    return this.physicalName;
  }

  public void setPhysicalName(String newPhysicalName)
  {
    this.physicalName = newPhysicalName;
  }

  protected void buildFromProperties(Properties props)
  {
    this.physicalName = props.getProperty("physicalName", this.physicalName);
  }

  protected void populateProperties(Properties props)
  {
    props.put("physicalName", this.physicalName);
  }

  public boolean isTemporary()
  {
    return (getDestinationType() == 2) || (getDestinationType() == 4);
  }

  public boolean isTopic()
  {
    return (getDestinationType() == 1) || (getDestinationType() == 2);
  }

  public boolean isQueue()
  {
    return !isTopic();
  }

  public String toString()
  {
    return this.physicalName;
  }

  public int hashCode()
  {
    int answer = -889275714;

    if (this.physicalName != null) {
      answer = this.physicalName.hashCode();
    }
    if (isTopic()) {
      answer ^= 16433067;
    }
    return answer;
  }

  public boolean equals(Object obj)
  {
    boolean result = this == obj;
    if ((!result) && (obj != null) && ((obj instanceof ActiveMQDestination))) {
      ActiveMQDestination other = (ActiveMQDestination)obj;
      result = (getDestinationType() == other.getDestinationType()) && (this.physicalName.equals(other.physicalName));
    }

    return result;
  }

  public static void writeToStream(ActiveMQDestination destination, DataOutput dataOut)
    throws IOException
  {
    if (destination != null) {
      dataOut.write(destination.getDestinationType());
      dataOut.writeUTF(destination == null ? "" : destination.getPhysicalName());
    }
    else {
      dataOut.write(10);
    }
  }

  public static ActiveMQDestination readFromStream(DataInput dataIn)
    throws IOException
  {
    int type = dataIn.readByte();
    if (type == 10) {
      return null;
    }
    ActiveMQDestination result = null;
    if (type == 1) {
      result = new ActiveMQTopic();
    }
    else if (type == 2) {
      result = new ActiveMQTemporaryTopic();
    }
    else if (type == 3) {
      result = new ActiveMQQueue();
    }
    else {
      result = new ActiveMQTemporaryQueue();
    }
    result.setPhysicalName(dataIn.readUTF());
    return result;
  }

  public static String createTemporaryName(String clientId)
  {
    return "{TD{" + clientId + "}TD}";
  }

  public static String getClientId(ActiveMQDestination destination)
  {
    String answer = null;
    if ((destination != null) && (destination.isTemporary())) {
      String name = destination.getPhysicalName();
      int start = name.indexOf("{TD{");
      if (start >= 0) {
        start += "{TD{".length();
        int stop = name.lastIndexOf("}TD}");
        if ((stop > start) && (stop < name.length())) {
          answer = name.substring(start, stop);
        }
      }
    }
    return answer;
  }

  public boolean isWildcard()
  {
    if (this.physicalName != null) {
      return (this.physicalName.indexOf("*") >= 0) || (this.physicalName.indexOf(">") >= 0);
    }

    return false;
  }

  public static ActiveMQDestination transformDestination(Destination destination)
    throws JMSException
  {
    ActiveMQDestination result = null;
    if (destination != null) {
      if ((destination instanceof ActiveMQDestination)) {
        result = (ActiveMQDestination)destination;
      }
      else if ((destination instanceof TemporaryQueue)) {
        result = new ActiveMQTemporaryQueue(((Queue)destination).getQueueName());
      }
      else if ((destination instanceof TemporaryTopic)) {
        result = new ActiveMQTemporaryTopic(((Topic)destination).getTopicName());
      }
      else if ((destination instanceof Queue)) {
        result = new ActiveMQTemporaryQueue(((Queue)destination).getQueueName());
      }
      else if ((destination instanceof Topic)) {
        result = new ActiveMQTemporaryTopic(((Topic)destination).getTopicName());
      }
    }

    return result;
  }
}